package btb.net;

import java.io.IOException;

import com.esotericsoftware.kryonet.Client;
import com.esotericsoftware.kryonet.Connection;
import com.esotericsoftware.kryonet.Listener;
import com.esotericsoftware.minlog.Log;

import btb.engine.ATask;
import btb.engine.CEvent;
import btb.engine.CTaskMessenger;
import btb.net.CNetwork.NAuthenticate;
import btb.net.CNetwork.NChatMessage;
import btb.net.CNetwork.NChatOpResults;
import btb.net.CNetwork.NRegister;
import btb.net.CNetwork.NRegisterClient;
import btb.net.CNetwork.NUpdate;
import btb.net.CNetwork.NValidate;
import btb.util.CLogger;

public class CMetaClientTask extends ATask
{
	public static final int LOGIN_NONE		= -2;
 	public static final int LOGIN_PASS 		= 0;
 	public static final int LOGIN_FAIL		= -1;
 	public static final int LOGIN_EXISTS	= 1;
	
	protected Client client = null;
	protected String name = "Unknown";
	
	protected int networkType = CNetwork.META_CLIENT;
	
	protected boolean setUp = true;
	
	protected String validationKey;
	protected int loginStatus;
		
	protected Listener metaListener = new Listener()
	{
		public void received(Connection _c, Object _o)
		{
			if(_o instanceof NRegister)
			{
				NRegisterClient client = new NRegisterClient();
				client.networkType = CMetaClientTask.this.networkType;
				client.name = CMetaClientTask.this.name;
				CMetaClientTask.this.client.sendTCP(client);					
			}
			else if(_o instanceof NUpdate)
			{
				
			}
			else if(_o instanceof NValidate)
			{
				NValidate validation = (NValidate)_o;
				
				if(validation.validationKey != null && !validation.validationKey.equals("") && !validation.validationKey.equals("FAIL"))
				{
					CMetaClientTask.this.validationKey = validation.validationKey;
					loginStatus = LOGIN_PASS;
				}
				else
				{
					loginStatus = LOGIN_FAIL;
				}
				
				if(Log.TRACE)
					Log.trace("game client", "Validation Key received: " + validation.validationKey);
			}
		}
	};
	
	public CMetaClientTask(ATask _parentTask, int _taskId, CTaskMessenger _mailbox) {
		super(_parentTask, _taskId, _mailbox);
		this.loginStatus = LOGIN_NONE;
	}
	
	public void handleDeath() {
		
	}
	
	public void handleEvent(CEvent _event) {		
		if(CNetworkEvent.class.isAssignableFrom(_event.getClass())) {
			CNetworkEvent cne = (CNetworkEvent)_event;
			
			String payload;
			int pos;
			
			switch(_event.getEventType()) {
				case CNetworkEvent.CNE_LOGIN_EVENT:
					payload = (String) cne.getEventPayload();
					pos = payload.indexOf('%');
					
					String username = payload.substring(0, pos);
					
					String password = payload.substring(pos + 1, payload.length() - 1);
					
					NAuthenticate authenticate = new NAuthenticate();
					authenticate.user = username;
					authenticate.pass = password;
					this.client.sendTCP(authenticate);
					break;
				case CNetworkEvent.CNE_LOGOUT_EVENT:
					this.loginStatus = CMetaClientTask.LOGIN_NONE;
					if(this.tearDown())
						this.kill();
					else
						CLogger.cond_error("client task", "Unable to tear down client task");
					break;
				case CNetworkEvent.CNE_UNDEFINED_EVENT: break;
				default: break;
			}
		}
	}
	
	public boolean isConnected() {
		return this.client != null && this.client.isConnected();
	}
	
	public void register(Connection _c, NRegister _r) {
		
	}
	
	public void setFriendlyName(String _name) {
		this.name = _name;
	}
	
	public boolean setUp()
	{
		boolean success = true;
		
		this.client = new Client();
		this.client.start();
		
		CNetwork.register(this.client);
		
		this.client.addListener(this.metaListener);
		
		try
		{
			this.client.connect(5000, CNetwork.META_SERVER_HOST, CNetwork.META_SERVER_PORT);
		}
		catch (IOException ioe)
		{
			success = false;
			ioe.printStackTrace();
		}
		
		return success;
	}
	
	public boolean tearDown() {
		boolean success = true;
		
		if(this.isConnected()) {
			this.client.stop();
			this.client = null;
			this.validationKey = "";
		} else
			success = false;
		
		return success;
	}

	public void update() {
		this.handleMail();
	}
	
	public void update(Connection _c, NUpdate _u)
	{
		
	}
	
	public synchronized int getLoginStatus(){return loginStatus;}
	public synchronized void setLoginStatus(int _loginStatus){loginStatus = _loginStatus;}
}
